/**
 * 
 */
package ro.dta.idbi.patterns;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import ro.dta.idbi.interfaces.IntegrationOperation;
import ro.dta.idbi.model.AbstractPattern;
import ro.dta.idbi.model.AbstractPrimitivePattern;
import uk.ac.ic.doc.automed.IntegrityException;
import uk.ac.ic.doc.automed.NotFoundException;
import uk.ac.ic.doc.automed.reps.Schema;
import uk.ac.ic.doc.automed.reps.SchemaObject;

/**
 * <b>Reverse transformation of the columns to supertype transformation
 * pattern</b>
 * 
 * Example of use:<br />
 * 
 * <code>col_to_subtypes(&lt;&lt;parent_table,col&gt;&gt;, &lt;&lt;table1&gt;&gt;,&lt;&lt;table2&gt;&gt;, ..., &lt;&lt;tablen&gt;&gt;)</code>
 * <br />
 * 
 * @author Tudor Dobrila
 * 
 */
public class ColToSupertypeRev extends AbstractPattern {

	/**
	 * Name of the pattern
	 */
	public static final String NAME = "Column to subtypes";

	/**
	 * Description of the pattern
	 */
	public static final String DESCRIPTION = "Distribute column to subtypes";

	/**
	 * Name of the command associated with the pattern
	 */
	public static final String COMMAND = "col_to_subtypes";

	/**
	 * Integration phase during which the command is applied
	 */
	public static final EnumSet<IntegrationOperation> OPERATION = EnumSet
			.of(IntegrationOperation.CONFORMING);

	/**
	 * Column in the parent table to be split amongst child tables
	 */
	private String parentColStr;

	/**
	 * (Table,column) representation of the column in the parent table
	 */
	private Entry<String, String> parentCol;

	/**
	 * Child tables
	 */
	private ArrayList<String> tables;

	/**
	 * Column to table pattern class constructor
	 * 
	 * @param sourceSchema
	 *            Source schema over which the transformation is applied
	 */
	public ColToSupertypeRev(final Schema sourceSchema) throws NotFoundException,
			IntegrityException {
		super(sourceSchema);

		pattern = Pattern.compile("^" + COMMAND + "[ ]*\\((" + COL_REGEX + ")" + COMMA_REGEX
				+ TABLE_SEQ_REGEX + "\\)$");
	}

	/**
	 * Column to table pattern class constructor
	 * 
	 * @param sourceSchema
	 *            Name of the source schema over which the transformation is
	 *            applied
	 */
	public ColToSupertypeRev(final String sourceSchema) throws NotFoundException,
			IntegrityException {
		this(Schema.getSchema(sourceSchema));
	}
	
	@Override
	protected List<String> getPrimitiveCommands() throws NotFoundException, IntegrityException {
		// Convert from backward (reverse transformation) syntax to forward
		// transformation syntax in order to be consistent with the extent
		// generator in the forward transformation
		String parentTbl = parentCol.getKey();
		List<String> colsStr = new ArrayList<String>();
		List<Entry<String, String>> cols = new ArrayList<Map.Entry<String, String>>();
		for (String t : tables) {
			String colName = "<<" + t + "," + parentCol.getValue() + ">>";
			colsStr.add(colName);
			cols.add(parseColName(colName));
		}
		
		SchemaObject col = sourceSchema.getSchemaObject(parentColStr);
		
		ColToSupertype forward = new ColToSupertype(sourceSchema, parentTbl, colsStr, cols, col.getSchemeDefinition());
		List<String> commands = forward.getPrimitiveCommands();
		List<String> result = new ArrayList<String>();
		for (String cmd : commands) {
			result.add(0, AbstractPrimitivePattern.getReverseTrans(cmd));
		}
		
		return result;
	}

	@Override
	protected boolean verify() {
		// TODO complete verification method
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ro.dta.idbi.model.AbstractPattern#parse(java.lang.String)
	 */
	@Override
	protected void parse(final String trans) {
		final Matcher matcher = pattern.matcher(trans);
		matcher.find();

		parentColStr = matcher.group(1);
		parentCol = parseColName(parentColStr);

		final List<String> tableList = splitValues(matcher.group(2));
		tables = new ArrayList<String>();

		for (String t : tableList) {
			tables.add(parseTableName(t));
		}
	}

}
